// Copyright Gary Evans 2006-2007.

using System;

using Taumuon.Jabuka.Physics;

using NUnit.Framework;

namespace Taumuon.Jabuka.Physics.Test
{
    /// <summary>
    /// Tests that a body moves according to Newton's
    /// laws of motion.
    /// </summary>
    [TestFixture]
    public class TestEulerRigidBody
    {
        #region Test Methods

        /// <summary>
        /// Tests that a body with zero mass can't be created.
        /// </summary>
        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void TestCreateABodyWithZeroMass()
        {
            EulerRigidBody body = new EulerRigidBody(new Vector(0.0, 0.0, 0.0),
                new Vector(0.0, 0.0, 0.0), 0.0);
        }

        /// <summary>
        /// Tests that a body with zero location can't be created.
        /// </summary>
        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void TestCreateABodyWithNullLocation()
        {
            EulerRigidBody body = new EulerRigidBody(null,
                new Vector(0.0, 0.0, 0.0), 1.0);
        }

        /// <summary>
        /// Tests that a body with zero velocity can't be created.
        /// </summary>
        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void TestCreateABodyWithNullVelocity()
        {
            EulerRigidBody body = new EulerRigidBody( new Vector(0.0, 0.0, 0.0),
                null, 1.0);
        }

        /// <summary>
        /// Tests that the ICloneable Clone works as expected.
        /// </summary>
        [Test]
        public void TestEulerRigidBodyClone()
        {
            Vector location = new Vector(4.5, 5.5, 6.5);
            Vector velocity = new Vector(7.5, 8.5, 9.5);
            double mass = 2.5;
            EulerRigidBody rigidBody = new EulerRigidBody(location,
                velocity, mass);
			rigidBody.ApplyForce(new Vector(-1.0, -2.0, -3.0));
            EulerRigidBody clone = rigidBody.Clone() as EulerRigidBody;
            Assert.IsNotNull(clone);
            Assert.IsFalse(object.ReferenceEquals(rigidBody, clone));

            // Check that memberwise copy called:
            Assert.AreEqual(2.5, clone.Mass);

            // Check that members are cloned:
            Assert.IsFalse(object.ReferenceEquals(
                rigidBody.Location, clone.Location), "Location references shouldn't be the same");
            Assert.IsFalse(object.ReferenceEquals(
                rigidBody.Velocity, clone.Velocity), "Velocity references shouldn't be the same");
			Assert.IsFalse(object.ReferenceEquals(
				rigidBody.AppliedForce, clone.AppliedForce), "AppliedForce references shouldn't be the same");

			Assert.IsTrue(
				TestVector.AreVectorValuesCorrect(clone.Location, 4.5, 5.5, 6.5),
				"Cloned Location not as expected");
			Assert.IsTrue(
				TestVector.AreVectorValuesCorrect(clone.Velocity, 7.5, 8.5, 9.5),
				"Cloned Velocity not as expected");
			Assert.IsTrue(
				TestVector.AreVectorValuesCorrect(clone.AppliedForce, -1.0, -2.0, -3.0),
				"Cloned AppliedForce not as expected");
        }

		/// <summary>
		/// Tests that the EulerRigidBody's members are correctly assigned from
		///  another EulerRigidBody
		/// </summary>
		[Test]
		public void TestAssignFromEulerRigidBody()
		{
			Vector location = new Vector(1.4, 2.4, 3.4);
			Vector velocity = new Vector(1.3, 2.3, 3.3);
			double mass = -5.7;
			EulerRigidBody eulerRigidBody = new
				EulerRigidBody(new Vector(), new Vector(), double.NaN);
			EulerRigidBody eulerRigidBody2 = new
				EulerRigidBody(location, velocity, mass);
			eulerRigidBody2.ApplyForce(new Vector(-1.0, -2.0, -3.0));

			eulerRigidBody.AssignFromEulerRigidBody(eulerRigidBody2);

			Assert.IsTrue(
				TestVector.AreVectorValuesCorrect(eulerRigidBody.Location, 1.4, 2.4, 3.4),
				"Location not as expected");
			Assert.IsTrue(
				TestVector.AreVectorValuesCorrect(eulerRigidBody.Velocity, 1.3, 2.3, 3.3),
				"Velocity not as expected");
			Assert.IsTrue(
				TestVector.AreVectorValuesCorrect(eulerRigidBody.AppliedForce, -1.0, -2.0, -3.0),
				"AppliedForce not as expected");
			Assert.AreEqual(-5.7, eulerRigidBody.Mass);
		}

        #endregion Test Methods
    }
}
